{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "is_executing": false
    }
   },
   "outputs": [],
   "source": [
    "from gs_quant.session import Environment, GsSession\n",
    "from gs_quant.instrument import FXKnockout\n",
    "from gs_quant.markets.portfolio import Portfolio\n",
    "from datetime import date\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# external users should substitute their client id and secret; please skip this step if using internal jupyterhub\n",
    "GsSession.use(Environment.PROD, client_id=None, client_secret=None, scopes=('run_analytics',))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# get list of properties of an fx knockout - Note the knockout instrument will also do RKO (Reverse Knockout)\n",
    "FXKnockout.properties()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# in this example we will construct and price a portfolio of FXKnockouts\n",
    "fx_kos = Portfolio()\n",
    "\n",
    "# you don't need to specify any parameters to get a valid trade.  All properties have defaults\n",
    "fx_kos.append(FXKnockout())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# knock_in_or_out controls whether the option exits if the barrier_level is breached (knockout) or whether the option\n",
    "# only starts once the barrier_level is breached.  Switch from a KO to an RKO.\n",
    "\n",
    "from gs_quant.common import InOut\n",
    "fx_kos.append(FXKnockout(barrier_level=.95, knock_in_or_out=InOut.Out))\n",
    "fx_kos.append(FXKnockout(barrier_level=.6, knock_in_or_out='In'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# knock_up_or_down controls whether which direction breaches are measured from\n",
    "\n",
    "from gs_quant.common import UpDown\n",
    "fx_kos.append(FXKnockout(barrier_level=.95, knock_up_or_down=UpDown.Up))\n",
    "fx_kos.append(FXKnockout(barrier_level=.6, knock_up_or_down='Down'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# buy_sell indicates whether the option is bought (long) or sold (short) \n",
    "# It can be represented by the BuySell enum or a string \n",
    "fx_kos.append(FXKnockout(buy_sell='Buy'))\n",
    "\n",
    "from gs_quant.common import BuySell\n",
    "fx_kos.append(FXKnockout(buy_sell=BuySell.Sell))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# put_call indicates whether the option is a put or call; it can be represented by the OptionType enum or a string\n",
    "fx_kos.append(FXKnockout(option_type='Put'))\n",
    "\n",
    "from gs_quant.common import OptionType\n",
    "fx_kos.append(FXKnockout(option_type=OptionType.Call))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "is_executing": false,
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# pair is the FXKnockout's underlying currency pair. It is a string of two ccy iso codes, optionally separated \n",
    "# with a space (' '). The first currency is the base (transaction) currency and the second is the quote currency\n",
    "\n",
    "# In this case, base currency is 'EUR' and quote currency is 'GBP'\n",
    "# This option gives the purchasor the option to buy EUR at expiration\n",
    "fx_kos.append(FXKnockout(buy_sell=BuySell.Buy, option_type=OptionType.Call, pair='EUR GBP'))\n",
    "\n",
    "# Here, base currency is 'GBP' and quote currency is 'USD'\n",
    "# This option gives the purchasor the option to sell GBP at expiration\n",
    "fx_kos.append(FXKnockout(buy_sell=BuySell.Buy, option_type=OptionType.Put, pair='GBPUSD'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# notional_currency is the notional amount's denominated currency\n",
    "# It can be a Currency enum or a string. By default, notional_currency will match the base currency\n",
    "\n",
    "# In this case, notional_currency of a EURGBP Call is EUR. \n",
    "from gs_quant.common import Currency\n",
    "fx_kos.append(FXKnockout(option_type = OptionType.Call, pair='EUR GBP', notional_currency = Currency.EUR ))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# notional_amount is the quantity of the base currency to be exchanged in the future; it can be a string (eg: '100mm')\n",
    "# or a double (10e8). By definition, notional_amount_other_currency is the notional amount in the quoted currency. It can be a Currency enum or a string \n",
    "# by default, notional_amount_other_currency will be the product of 'notional_amount' and 'strike_price'\n",
    "\n",
    "# Here, a EURGBP Call has a notional of 10mm EUR\n",
    "fx_kos.append(FXKnockout(option_type = OptionType.Call, pair='EUR GBP', notional_currency = Currency.EUR, \n",
    "                         notional_amount='10m'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "strike_price is the exchange rate stuck for the FXOption's underlying currency pair, which can be specified by a double \n",
    "or a string. If a string is used, it represents a relative value. When the trade is resolved, we solve for the strike_price \n",
    "\n",
    "The specific solver keys are: \n",
    "    - 'S'    - current spot rate\n",
    "    - 'F'    - forward\n",
    "    - 'ATM'  - At the Money \n",
    "    - 'ATMF' - At the Money Forward\n",
    "    - 'D'    - Delta Strikes\n",
    "    - 'P'    - Premium\n",
    "\n",
    "You can use these keys to strike_price with the following formats: \n",
    "    - For S, F, ATM, ATMF: 's*1.1', 'F+10%', '1.05*ATMF+.01'\n",
    "    - For Delta Strikes, specify the option delta: '25D', '20D-.01', etc.\n",
    "    - You can also solve for Premium: P=<target premium>, P=<target premium> P=,<target>%, PPct=<target> \n",
    "\n",
    "\"\"\"\n",
    "\n",
    "# Here the option is bought to purchase 95mm EUR at expiration  \n",
    "fx_kos.append(FXKnockout(buy_sell=BuySell.Buy, pair='EURGBP', option_type='Call', notional_amount=10e8, \n",
    "                         strike_price=.95))\n",
    "\n",
    "# Here the option is sold to sell 100k of EUR at the current spot rate on expiration\n",
    "fx_kos.append(FXKnockout(buy_sell=BuySell.Sell, pair='EURGBP', option_type=OptionType.Put, notional_amount='100k', \n",
    "                         strike_price='S'))\n",
    "\n",
    "# The option is sold to purchase AUD at the Forward rate + 1%\n",
    "fx_kos.append(FXKnockout(buy_sell=BuySell.Sell, pair='AUDJPY', option_type=OptionType.Call, strike_price='F+1%'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# method_of_settlement indicates whether the option is cash or physically settled and can be either the \n",
    "# OptionSettlementMethod Enum or a string \n",
    "from gs_quant.common import OptionSettlementMethod\n",
    "fx_kos.append(FXKnockout(method_of_settlement=OptionSettlementMethod.Cash))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# premium_currency is the premium amount's denominated currency\n",
    "# It can be a Currency enum or a string. By default, premium_currency will match the base currency\n",
    "\n",
    "# In this case, premium_currency of a EURGBP Put is EUR \n",
    "fx_kos.append(FXKnockout(option_type = OptionType.Put, pair='EUR GBP', premium_currency = Currency.EUR ))\n",
    "\n",
    "# premium_payment_date is the date the premium is exchanged. It can either be a date or string\n",
    "# It can be set to 's' which indicates spot premium\n",
    "fx_kos.append(FXKnockout(option_type = OptionType.Call, pair='EUR GBP', premium_payment_date='spot' ))\n",
    "\n",
    "# or set to 'fwd' or 'forward' to indicate forward premium\n",
    "fx_kos.append(FXKnockout(option_type = OptionType.Call, pair='EUR GBP', premium_payment_date='fwd' ))\n",
    "\n",
    "# premium is the price of the option contract. It can be a float or a string\n",
    "fx_kos.append(FXKnockout(option_type = OptionType.Call, premium= -5e6))\n",
    "\n",
    "# It is possible to solve for the strike_price based on a certain Premium\n",
    "# The below resolves the strike_price such that the option premium is -£5mm\n",
    "fx_kos.append(FXKnockout(pair='AUD JPY', option_type = OptionType.Call, strike_price= 'P=-5mm', premium_currency=Currency.AUD))\n",
    "\n",
    "# The below resolves the strike_price such that the option premium is 5% of the total amount exchanged if the option\n",
    "# is exercised\n",
    "fx_kos.append(FXKnockout(pair = 'AUD JPY', option_type = OptionType.Call, strike_price= 'Premium=5%', premium_currency=Currency.JPY))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "pd.DataFrame(fx_kos.price())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "pycharm": {
   "stem_cell": {
    "cell_type": "raw",
    "metadata": {
     "collapsed": false
    },
    "source": []
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
